package com.indi.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.indi.common.constant.ProductConstant.AttrEnum;
import com.indi.common.utils.PageUtils;
import com.indi.common.utils.Query;
import com.indi.gulimall.product.dao.AttrAttrGroupRelationDao;
import com.indi.gulimall.product.dao.AttrDao;
import com.indi.gulimall.product.dao.AttrGroupDao;
import com.indi.gulimall.product.dao.CategoryDao;
import com.indi.gulimall.product.entity.AttrAttrGroupRelationEntity;
import com.indi.gulimall.product.entity.AttrEntity;
import com.indi.gulimall.product.entity.AttrGroupEntity;
import com.indi.gulimall.product.entity.CategoryEntity;
import com.indi.gulimall.product.mapstruct.ProductCovertBasic;
import com.indi.gulimall.product.service.AttrService;
import com.indi.gulimall.product.service.CategoryService;
import com.indi.gulimall.product.vo.AttrRespVO;
import com.indi.gulimall.product.vo.AttrVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
    @Resource
    private AttrAttrGroupRelationDao relationDao;

    @Resource
    private CategoryDao categoryDao;

    @Resource
    private AttrGroupDao attrGroupDao;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveAttr(AttrVO attrVO) {
        // 保存基本数据
        AttrEntity attr = ProductCovertBasic.INSTANCE.attrVOToAttr(attrVO);
        this.save(attr);

        if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 保存关联关系
            AttrAttrGroupRelationEntity relation = new AttrAttrGroupRelationEntity();

            relation.setAttrGroupId(attrVO.getAttrGroupId());
            relation.setAttrId(attr.getAttrId());
            relationDao.insert(relation);
        }
    }

    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long categoryId, String attrType) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attr_type",
                "base".equalsIgnoreCase(attrType)
                        ? AttrEnum.ATTR_TYPE_BASE.getCode()
                        : AttrEnum.ATTR_TYPE_SALE.getCode()
        );

        if (categoryId != 0) {
            queryWrapper.eq("category_id", categoryId);
        }


        IPage<AttrEntity> page = getPage(params, queryWrapper);

        List<AttrEntity> recordList = page.getRecords();
        List<AttrRespVO> attrRespVOList = recordList.stream().map(attr -> {
            AttrRespVO attrRespVO = ProductCovertBasic.INSTANCE.attrToAttrRespVO(attr);
            // 设置分类名称
            CategoryEntity category = categoryDao.selectById(attr.getCategoryId());
            if (category != null) {
                attrRespVO.setCategoryName(category.getName());
            }

            if ("base".equalsIgnoreCase(attrType)) {
                // 先查分组id
                QueryWrapper<AttrAttrGroupRelationEntity> relationWrapper = new QueryWrapper<>();
                relationWrapper.eq("attr_id", attr.getAttrId());
                AttrAttrGroupRelationEntity relation = relationDao.selectOne(relationWrapper);

                // 再根据分组id查分组名称
                if (relation != null && relation.getAttrGroupId() != null) {
                    AttrGroupEntity attrGroup = attrGroupDao.selectById(relation.getAttrGroupId());
                    if (attrGroup != null) {
                        attrRespVO.setGroupName(attrGroup.getAttrGroupName());
                    }
                }
            }

            return attrRespVO;
        }).collect(Collectors.toList());

        PageUtils pageUtils = new PageUtils(page);
        pageUtils.setList(attrRespVOList);
        return pageUtils;
    }

    @Resource
    private CategoryService categoryService;

    @Cacheable(value = "attr", key = "'attr_info:'+#root.args[0]")
    @Override
    public AttrRespVO getAttrInfo(Long attrId) {
        AttrEntity attr = this.getById(attrId);
        AttrRespVO attrRespVO = ProductCovertBasic.INSTANCE.attrToAttrRespVO(attr);

        if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 设置分组id、分组名称
            AttrAttrGroupRelationEntity relation = relationDao.selectOne(
                    new QueryWrapper<AttrAttrGroupRelationEntity>().eq("attr_id", attrId)
            );

            if (relation != null) {
                attrRespVO.setAttrGroupId(relation.getAttrGroupId());
                AttrGroupEntity attrGroup = attrGroupDao.selectById(relation.getAttrGroupId());
                if (attrGroup != null) {
                    attrRespVO.setGroupName(attrGroup.getAttrGroupName());
                }
            }
        }


        // 设置分类的完整路径、分类名称
        Long[] categoryPath = categoryService.findCategoryPath(attr.getCategoryId());
        attrRespVO.setCategoryPath(categoryPath);
        CategoryEntity category = categoryDao.selectById(attr.getCategoryId());
        if (category != null) {
            attrRespVO.setCategoryName(category.getName());
        }

        return attrRespVO;
    }

    @Override
    public void updateAttr(AttrVO attrVO) {
        AttrEntity attr = ProductCovertBasic.INSTANCE.attrVOToAttr(attrVO);
        this.updateById(attr);


        if (attr.getAttrType() == AttrEnum.ATTR_TYPE_BASE.getCode()) {
            // 根据分组关联是否存在决定，新增/修改分组关联
            AttrAttrGroupRelationEntity relation = new AttrAttrGroupRelationEntity();

            Integer count = relationDao.selectCount(new QueryWrapper<AttrAttrGroupRelationEntity>().eq("attr_id", attrVO.getAttrId()));

            if (count > 0) {
                // 更改分类的时候，可能会导致分组id清空，需要做空值判断
                relationDao.update(relation, new UpdateWrapper<AttrAttrGroupRelationEntity>().eq("attr_id", attrVO.getAttrId())
                        .set("attr_group_id", attrVO.getAttrGroupId() == null ? null : attrVO.getAttrGroupId()));
            } else {
                relation.setAttrGroupId(attrVO.getAttrGroupId());
                relation.setAttrId(attrVO.getAttrId());
                relationDao.insert(relation);
            }
        }
    }

    @Override
    public List<AttrEntity> getRelationAttr(Long attrGroupId) {
        // 根据分组id查出所有的关联记录
        List<AttrAttrGroupRelationEntity> relationList = relationDao.selectList(
                new QueryWrapper<AttrAttrGroupRelationEntity>().eq("attr_group_id", attrGroupId)
        );
        // 将所有关联记录的规格参数id提取出来
        List<Long> attrIds = relationList.stream().map(relation ->
                relation.getAttrId()
        ).collect(Collectors.toList());

        List<AttrEntity> attrList = new ArrayList<>();
        if (attrIds != null && attrIds.size() > 0) {
            // 根据规格参数的id集合查出所有的规格参数
            attrList = (List<AttrEntity>) this.listByIds(attrIds);
        }
        return attrList;
    }

    @Override
    public PageUtils getNoRelationAttr(Long attrGroupId, Map<String, Object> params) {
        // 规格参数、参数分组都属于分类下的信息，规格参数与参数分组又通过一张关系表，将两者关联在一起
        // 分类：手机
        // 规格参数：上市年份、机身重量（g）
        // 参数分组：主体、基本信息...


        // 当前分组，只能关联自己所属分类中的规格参数
        AttrGroupEntity attrGroup = attrGroupDao.selectById(attrGroupId);
        Long categoryId = attrGroup.getCategoryId();

        // 1、通过当前分类id，找到当前分类下的所有分组
        List<AttrGroupEntity> attrGroups = attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("category_id", categoryId));

        // 2、将所有分组的id提取出来
        List<Long> attrGroupIds = attrGroups.stream().map(item -> item.getAttrGroupId()).collect(Collectors.toList());

        // 3、通过所有分组的id，找出所有分组的关联关系
        List<AttrAttrGroupRelationEntity> relations = relationDao.selectList(new QueryWrapper<AttrAttrGroupRelationEntity>()
                .in("attr_group_id", attrGroupIds));

        // 4、将关联的参数id提取出来
        List<Long> attrIds = relations.stream().map(item -> item.getAttrId()).collect(Collectors.toList());

        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>().eq("category_id", categoryId)
                .eq("attr_type", AttrEnum.ATTR_TYPE_BASE.getCode());

        // 5、将有关联关系的规格参数移除
        if (attrIds != null && attrIds.size() > 0) {
            queryWrapper.notIn("attr_id", attrIds);
        }

        IPage<AttrEntity> page = getPage(params, queryWrapper);
        return new PageUtils(page);
    }

    @Override
    public void removeAttrs(List<Long> attrIds) {
        baseMapper.deleteBatchIds(attrIds);
        relationDao.delete(new QueryWrapper<AttrAttrGroupRelationEntity>().in("attr_id", attrIds));
    }

    @Override
    public List<Long> getSearchAttrIds(List<Long> attrIds) {
        List<Long> searchAttrIds = this.listObjs(new QueryWrapper<AttrEntity>().select("attr_id").in("attr_id", attrIds)
                .eq("search_type", 1)).stream().map(o -> (Long) o).collect(Collectors.toList());
        return searchAttrIds;
    }

    /**
     * 获取分页信息
     *
     * @param params       查询参数
     * @param queryWrapper 查询条件
     * @return
     */
    private IPage<AttrEntity> getPage(Map<String, Object> params, QueryWrapper<AttrEntity> queryWrapper) {
        String key = (String) params.get("key");
        if (StringUtils.isNotEmpty(key)) {
            queryWrapper.and(wrapper ->
                    wrapper.eq("attr_id", key).or().like("attr_name", key)
            );
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                queryWrapper
        );
        return page;
    }
}